package vsy.buzzwordbingo.model.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import vsy.buzzwordbingo.model.*;

public class GameImpl implements Game {
	private String id;
	private String title;
	private int size;
	private String description;
	private Player owner;
	private List<String> buzzwords;

	private List<Player> players;
	private List<GameBoard> boards;
	
	private Player winner;
	
	private long creationTime;
	private long lastModificationTime;

	public GameImpl(String id, String title, int size, String description, Player owner, List<String> buzzwords, Player winner, long creationTime, long lastModificationTime ) {
		this(id, title, size, description, owner, buzzwords);
		this.lastModificationTime = lastModificationTime;
		this.creationTime = creationTime;
		this.winner = winner;
	}
	
	public GameImpl(String id, String title, int size, String description, Player owner, List<String> buzzwords) {
		this.id = id;
		this.title = title;
		this.size = size;
		this.description = description;
		this.owner = owner;
		this.players = new ArrayList<Player>();
		this.boards = new ArrayList<GameBoard>();
		this.buzzwords = new ArrayList<String>(buzzwords.size());
		this.buzzwords.addAll(buzzwords);
		this.creationTime = updateLastModificationTime();
	}

	@Override
	public String getId() {
		return this.id;
	}

	@Override
	public String getTitle() {
		return this.title;
	}

	@Override
	public int getSize() {
		return size;
	}

	@Override
	public String getDescription() {
		return description;
	}

	@Override
	public Player getOwner() {
		return owner;
	}

	@Override
	public List<String> getBuzzwords() {
		return Collections.unmodifiableList(buzzwords);
	}

	@Override
	public List<Player> getPlayers() {
		return Collections.unmodifiableList(players);
	}
	
	@Override
	public List<GameBoard> getBoards() {
		return Collections.unmodifiableList(boards);
	}

	@Override
	public Player getWinner() {
		if (this.winner == null) {
			for (GameBoard board: this.boards) {
				if (board.isFinished()) {
					this.winner = board.getPlayer();
					return this.winner;
				}
			}
		}
		return this.winner;
	}

	@Override
	public long getCreationTime() {
		return this.creationTime;
	}

	@Override
	public long getLastModificationTime() {
		return this.lastModificationTime;
	}

	@Override
	public long updateLastModificationTime() {
		return (this.lastModificationTime = System.currentTimeMillis());
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Game)) 
			return false;
		
		Game game = (Game)obj;
		return  (game.getId().equals(id)) &&
				(game.getTitle().equals(title)) &&
				(game.getSize() == size) &&
				(game.getDescription().equals(description)) &&
				(game.getOwner().equals(owner));
	}
	
	@Override
	public int hashCode() {
		return this.id.hashCode();
	}
	
	@Override
	public String toString() {
		return this.id;
	}


	@Override
	public GameBoard joinGame(Player player) {
		GameBoard playerBoard = null;
		if (!this.players.contains(player)) {
			this.players.add(player);
		}
		for (GameBoard board : this.boards) {
			if (board.getPlayer() == player) {
				playerBoard = board;
			}
		}
		if (playerBoard == null) {
			playerBoard = new GameBoardImpl(player, this, this.getBuzzwords(), this.getSize());
			this.boards.add(playerBoard);
		}
		player.joinGame(this, playerBoard);
		return playerBoard;
	}

	@Override
	public void leaveGame(Player player) {
		if (this.players.contains(player)) {
			this.players.remove(player);
		}
	}

	@Override
	public void kick(Player player) {
		leaveGame(player);
		GameBoard playerBoard = null;
		for (GameBoard board : this.boards) {
			if (board.getPlayer() == player) {
				playerBoard = board;
				this.boards.remove(board);
			}
		}
		player.leaveGame(this, playerBoard);
	}
}